home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mush-7.1.1 / tool.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-02  |  14.7 KB  |  547 lines

  1. /* @(#)tool.c    (c) copyright    10/15/86 (Dan Heller) */
  2.  
  3. /* tool.c --make the mailtool windows, panels, etc... */
  4. #include "mush.h"
  5.  
  6. #ifndef FONTDIR
  7. #define FONTDIR          "/usr/lib/fonts/fixedwidthfonts/"
  8. #endif /* FONTDIR */
  9.  
  10. extern void print_sigwinch(), make_hdr_sw();
  11. extern Notify_value fkey_interposer();
  12.  
  13. static void init_cursors(), geticon();
  14.  
  15. extern Panel /* panels.c */
  16.     make_hdr_panel(), make_main_panel();
  17.  
  18. Panel
  19.     main_panel,        /* the main panel dealing with generic items */
  20.     hdr_panel;        /* panel which contains message header specific items */
  21.  
  22. Textsw cprint_sw, mfprint_sw, wprint_sw;
  23. Frame compose_frame;
  24.  
  25. static char **choice_args, **button_args;
  26.  
  27. short dat_mail_icon_1[] = {
  28. #include "mail.icon.1"
  29. };
  30.  
  31. short dat_mail_icon_2[] = {
  32. #include "mail.icon.2"
  33. };
  34.  
  35. short dat_coffee_cup[] = {
  36.     0x0200,0x0100,0x0600,0x0800,0x0600,0x0100,0xFFF8,0x800C,
  37.     0x800A,0x4012,0x401C,0x2020,0x9048,0x7FF0,0x3FE0,0x0000
  38. };
  39.  
  40. mpr_static(mail_icon_image1, 64, 64, 1, dat_mail_icon_1);
  41. mpr_static(mail_icon_image2, 64, 64, 1, dat_mail_icon_2);
  42.  
  43. mpr_static(coffee_cup,      16, 16, 1, dat_coffee_cup);
  44.  
  45. /* public for hdr_sw.c */
  46. Cursor l_cursor, m_cursor, r_cursor;
  47. static Cursor coffee;
  48.  
  49. /* text and font will be set in mail_status() */
  50. Icon mail_icon;
  51.  
  52. static Notify_value scroll_hdr();
  53.  
  54. make_tool()
  55. {
  56.     Rect    mrect;       /* Position and size of icon label. */
  57.     struct stat rootbuf, tmpbuf;
  58.     char    *p;
  59.     struct pixfont *pf_open();
  60.  
  61.     if (p = do_set(set_options, "font")) {
  62.     char buf[MAXPATHLEN];
  63.     (void) sprintf(buf, "%s%s", FONTDIR, p);
  64.     if (!(mush_font = pf_open(buf)))
  65.         print("couldn't open font \"%s\"\nUsing default font.\n", buf);
  66.     }
  67.     if (!mush_font)
  68.     mush_font = pf_default();
  69.  
  70.     geticon();
  71.     check_icons();
  72.  
  73.     if (p = do_set(set_options, "screen_win"))
  74.     screen = atoi(p);
  75.     else
  76.     screen = 6;
  77.  
  78.     /* where to place text on mail icon -- how many messages there are */
  79.     mrect.r_left = l_width();
  80.     mrect.r_top = 58-l_height();
  81.     mrect.r_width = 3*l_width();
  82.     mrect.r_height = l_height();
  83.     (void) icon_set(mail_icon, ICON_LABEL_RECT, &mrect, NULL);
  84.  
  85.     (void) window_set(tool,
  86.     FRAME_ICON,    mail_icon,
  87.     WIN_CONSUME_KBD_EVENTS,
  88.         WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS, NULL,
  89.     NULL);
  90.     (void) notify_interpose_destroy_func(tool, destroy_proc);
  91.  
  92.     choice_args = panel_make_list(
  93.     PANEL_MENU_TITLE_FONT, mush_font,
  94.     PANEL_DISPLAY_LEVEL,    PANEL_NONE,
  95.     PANEL_SHOW_MENU,    TRUE,
  96.     PANEL_SHOW_MENU_MARK,    FALSE,
  97.     NULL);
  98.  
  99.     button_args = panel_make_list(
  100.     PANEL_FEEDBACK,        PANEL_INVERTED,
  101.     PANEL_SHOW_MENU,    FALSE,
  102.     NULL);
  103.  
  104.     hdr_panel = make_hdr_panel(tool, choice_args, button_args);
  105.  
  106.     make_hdr_sw(tool);
  107.  
  108.     main_panel = make_main_panel(tool, choice_args, button_args);
  109.  
  110.     /* main mush frame text subwindow for wprint() */
  111.     mfprint_sw = window_create(tool, TEXTSW,
  112.     WIN_BELOW,                      main_panel,
  113.     WIN_HEIGHT,                     l_height() * 4,
  114.     TEXTSW_READ_ONLY,               TRUE,
  115.     TEXTSW_BLINK_CARET,             FALSE,
  116.     TEXTSW_LINE_BREAK_ACTION,       TEXTSW_WRAP_AT_CHAR,
  117.     NULL);
  118.     /* order is important -- scroll_textwin should be called first! */
  119.     (void) notify_interpose_event_func(mfprint_sw,
  120.     fkey_interposer, NOTIFY_SAFE);
  121.     (void) notify_interpose_event_func(mfprint_sw,
  122.     scroll_textwin, NOTIFY_SAFE);
  123.  
  124.     /* text subwindow for paging messages */
  125.     p = do_set(set_options, "crt_win");
  126.     pager_textsw = window_create(tool, TEXTSW,
  127.     WIN_HEIGHT,            l_height() * (p? atoi(p) : 12),
  128.     TEXTSW_READ_ONLY,        TRUE,
  129.     TEXTSW_BLINK_CARET,        FALSE,
  130. #ifdef SUN_4_0 /* SunOS 4.0+ */
  131.     TEXTSW_LINE_BREAK_ACTION,    TEXTSW_WRAP_AT_WORD,
  132. #else /* SUN_4_0 */
  133.     TEXTSW_LINE_BREAK_ACTION,    TEXTSW_WRAP_AT_CHAR,
  134. #endif /* SUN_4_0 */
  135.     NULL);
  136.     /* order is important -- scroll_textwin should be called first! */
  137.     (void) notify_interpose_event_func(pager_textsw,
  138.     fkey_interposer, NOTIFY_SAFE);
  139.     (void) notify_interpose_event_func(pager_textsw,
  140.     scroll_textwin, NOTIFY_SAFE);
  141.  
  142.     (void) sprintf(blank, "%128c", ' ');
  143.     mrect = *(Rect *)window_get(hdr_sw, WIN_RECT);
  144.     pw_writebackground(hdr_win, 0,0, mrect.r_width, mrect.r_height, PIX_CLR);
  145.     istool = 2;
  146.     (void) fclose(stdin);
  147.     (void) fclose(stdout);
  148. #ifndef SUN_3_5
  149.     /* SunOS 3.5 takes tty modes for ttysws from stderr. */
  150.     (void) fclose(stderr);
  151. #endif /* SUN_3_5 */
  152.     (void) do_version();
  153.     init_cursors();
  154.     timeout_cursors(TRUE);
  155.     window_fit_height(tool);
  156. }
  157.  
  158. void
  159. close_frame()
  160. {
  161.     window_set(compose_frame, WIN_SHOW, FALSE, NULL);
  162. }
  163.  
  164. void
  165. make_compose_frame()
  166. {
  167.     char *p;
  168.     Textsw msg_sw;
  169.     Panel panel, make_compose_panel();
  170.  
  171. #ifdef SUN_3_5
  172.     if (nopenfiles(0) < 8) {
  173.     ok_box("Too many frames; close one, please.\n");
  174.     return;
  175.     }
  176. #endif /* SUN_3_5 */
  177.  
  178.     compose_frame = window_create(tool, FRAME,
  179.     FRAME_LABEL,        "Compose Letter",
  180.     FRAME_SHOW_LABEL,    TRUE,
  181.     FRAME_NO_CONFIRM,    TRUE,
  182.     FRAME_DONE_PROC,    close_frame,
  183.     WIN_SHOW,        TRUE,
  184.     NULL);
  185.  
  186.     panel = make_compose_panel(compose_frame, choice_args, button_args);
  187.  
  188. #ifdef CPRINT_SW
  189.     /* text subwindow for wprint() */
  190.     cprint_sw = window_create(compose_frame, TEXTSW,
  191.     WIN_HEIGHT,            l_height() * 4,
  192.     WIN_BELOW,            panel,
  193.     TEXTSW_READ_ONLY,        TRUE,
  194.     TEXTSW_BLINK_CARET,        FALSE,
  195.     TEXTSW_LINE_BREAK_ACTION,    TEXTSW_WRAP_AT_CHAR,
  196.     NULL);
  197.     notify_interpose_event_func(cprint_sw, scroll_textwin, NOTIFY_SAFE);
  198.     (void) notify_interpose_event_func(cprint_sw,
  199.     fkey_interposer, NOTIFY_SAFE);
  200. #else /* CPRINT_SW */
  201.     /* not enough fd's in SunOS 3.X for the extra textsw */
  202.     cprint_sw = (Textsw) 0;
  203. #endif /* CPRINT_SW */
  204.  
  205.     /* text subwindow for composing messages */
  206.     p = do_set(set_options, "msg_win");
  207.     msg_sw = window_create(compose_frame, TEXTSW,
  208. #ifdef CPRINT_SW
  209.     WIN_BELOW,            cprint_sw,
  210. #else /* CPRINT_SW */
  211.     WIN_BELOW,            panel,
  212. #endif /* CPRINT_SW */
  213.     WIN_HEIGHT,            l_height() * (p? atoi(p) : 24),
  214.     TEXTSW_READ_ONLY,        TRUE, /* set to false later */
  215.     TEXTSW_BLINK_CARET,        FALSE,
  216.     TEXTSW_LINE_BREAK_ACTION,    TEXTSW_WRAP_AT_CHAR,
  217.     TEXTSW_IGNORE_LIMIT,        TEXTSW_INFINITY,
  218.     NULL);
  219.     notify_interpose_event_func(msg_sw, fkey_interposer, NOTIFY_SAFE);
  220.     notify_interpose_event_func(msg_sw, edit_msg_textwin, NOTIFY_SAFE);
  221.  
  222.     /* Assign textsw (msg_sw) to panel for panel items' callbacks */
  223.     panel_set(panel, PANEL_CLIENT_DATA, msg_sw, NULL);
  224.  
  225.     /* tty subwindow */
  226.     if (!(tty_sw = window_create(compose_frame, TTY,
  227.     TTY_QUIT_ON_CHILD_DEATH, FALSE,
  228.     TTY_ARGV,        TTY_ARGV_DO_NOT_FORK,
  229.     WIN_CLIENT_DATA,    msg_sw,
  230.     WIN_SHOW,        FALSE,
  231.     WIN_WIDTH,        WIN_EXTEND_TO_EDGE,
  232.     WIN_BELOW,        msg_sw,
  233.     NULL)))
  234.     perror("tty_sw"), cleanup(0);
  235.  
  236.     window_fit_height(compose_frame);
  237. }
  238.  
  239. /*ARGSUSED*/
  240. void
  241. open_compose()
  242. {
  243.     if (compose_frame)
  244.     window_set(compose_frame, WIN_SHOW, TRUE, NULL);
  245.     else
  246.     make_compose_frame();
  247. }
  248.  
  249. parse_tool_opts(argcp, argv)
  250. int *argcp;
  251. char **argv;
  252. {
  253.     if (!(tool = window_create((Window) 0, FRAME,
  254.     FRAME_ARGC_PTR_ARGV, argcp, argv,
  255.     NULL)))
  256.     cleanup(0);
  257. }
  258.  
  259. /*
  260.  * used by both the hdr_sw (to scroll canvas) and by textsw's.
  261.  * Return values:
  262.  *  MUSH_SCROLL_TO (to scroll _to_ a particular location)
  263.  *  MUSH_SCROLL_RELATIVE (scroll relative our current location)
  264.  *  MUSH_SCROLL_IGNORE (not a scroll event and ignore it entirely (up events))
  265.  *  MUSH_SCROLL_PASS_EVENT (not a scroll event; pass it to next event handler)
  266.  * If absolute scrolling (scroll_to) then "amount" is set to 1 for beginning
  267.  * of textsw or 2 for end of textsw.
  268.  * User can precede a keyboard scrolling request by a "count" -- the
  269.  * count is typed by the user in digits: 5j = move 5 lines down.
  270.  * It is assumed that if the user moves the mouse after a digit is pressed,
  271.  * then he doesn't really want to adjust the scrolling amount and the 
  272.  * count is reset to the default (1).
  273.  */
  274. Scroll_action
  275. decode_scroll(client, event, len, amount)
  276. Notify_client client;
  277. Event    *event;
  278. int len, *amount;
  279. {
  280.     static int count;
  281.  
  282.     if (event_id(event) == LOC_MOVE) {
  283.     count = 0;
  284.     return MUSH_SCROLL_PASS_EVENT;
  285.     }
  286.  
  287.     *amount = 0;  /* Assume relative scroll */
  288.     if (ID == SCROLL_REQUEST)
  289.     return MUSH_SCROLL_PASS_EVENT;
  290.  
  291.     if (event_is_up(event))
  292.     return MUSH_SCROLL_PASS_EVENT;
  293.     if (event_is_ascii(event) && isdigit(event_id(event))) {
  294.     count = (count * 10) + event_id(event) - '0';
  295.     return MUSH_SCROLL_IGNORE;
  296.     }
  297. #ifdef SUN_4_0 /* SunOS 4.0+ */
  298.     /* returns sunview events for some ctl chars */
  299.     switch (event_action(event)) {
  300.     case ACTION_GO_LINE_FORWARD:
  301.     case ACTION_GO_COLUMN_FORWARD:
  302.         *amount = count ? count : 1;
  303.         count = 0;
  304.         return MUSH_SCROLL_RELATIVE;
  305.     case ACTION_GO_LINE_BACKWARD:
  306.     case ACTION_GO_COLUMN_BACKWARD:
  307.         *amount = count ? -count : -1;
  308.         count = 0;
  309.         return MUSH_SCROLL_RELATIVE;
  310.     case ACTION_GO_DOCUMENT_START:
  311.         *amount = 1;
  312.         count = 0;
  313.         return MUSH_SCROLL_TO;
  314.     case ACTION_GO_DOCUMENT_END:
  315.         *amount = 2;
  316.         count = 0;
  317.         return MUSH_SCROLL_TO;
  318.     }
  319. #endif /* SUN_4_0 */
  320.     /* for SunOS 3.5, assume default SunView key mapping */
  321.     /* a little redundancy for 4.0, but it's ok */
  322.     if (!event_is_ascii(event) && ID != KEY_RIGHT(14) && ID != KEY_RIGHT(8)
  323.     && ID != KEY_RIGHT(7) && ID != KEY_RIGHT(13))
  324.     /* may have to reset "count" here */
  325.     return MUSH_SCROLL_PASS_EVENT; /* Not a scroll event */
  326.     switch (event_id(event)) {
  327.     case KEY_RIGHT(7):    /* Home on new keyboards */
  328.         *amount = 1, count = 0;
  329.         return MUSH_SCROLL_TO;
  330.     case KEY_RIGHT(13):    /* End on new keyboards */
  331.         *amount = 2, count = 0;
  332.         return MUSH_SCROLL_TO;
  333.     case 'j': case KEY_RIGHT(14):    /* downarrow */
  334.         *amount = count ? count : 1;
  335.     when 'k': case KEY_RIGHT(8):    /* uparrow */
  336.         *amount = count ? -count : -1;
  337.     when 'F'-'@':    /* ^f */
  338.         *amount = count ? count * (len-1) : len - 1;
  339.     when 'D'-'@':    /* ^d */
  340.         *amount = len/2;
  341.     when 'B'-'@':    /* ^b */
  342.         *amount = -(count ? count * (1-len) : len - 1);
  343.     when 'U'-'@':    /* ^u */
  344.         *amount = -len/2;
  345.     when '\033':    /* Escape */
  346.         /* For SunOS 3.5 check to see if this is a cursor
  347.          * move key, i.e. ESC[A or ESC[B.
  348.          */
  349.         if (!(int)window_read_event(client, event) &&
  350.         event_id(event) == '[' &&
  351.         !(int)window_read_event(client, event))
  352.             if (event_id(event) == 'A') {
  353.             *amount = -1;
  354.             break;
  355.             } else if (event_id(event) == 'B') {
  356.             *amount = 1;
  357.             break;
  358.             }
  359.     default:
  360.         count = 0;
  361.         return event_is_ascii(event) ?
  362.         MUSH_SCROLL_IGNORE : MUSH_SCROLL_PASS_EVENT;
  363.     }
  364.     count = 0;
  365.     /* Scroll indicated amount if event is down, ignore up events */
  366.     return MUSH_SCROLL_RELATIVE;
  367. }
  368.  
  369. Notify_value
  370. scroll_textwin(textsw, event, arg, type)
  371. Textsw    textsw;
  372. Event    *event;
  373. Notify_arg    arg;
  374. Notify_event_type    type;
  375. {
  376.     int scroll_amount;
  377.  
  378.     switch (decode_scroll(textsw, event, textsw_screen_line_count(textsw),
  379.     &scroll_amount)) {
  380.     case MUSH_SCROLL_PASS_EVENT :
  381.         return notify_next_event_func(textsw, event, arg, type);
  382.     case MUSH_SCROLL_IGNORE:
  383.         return NOTIFY_IGNORED;
  384.     case MUSH_SCROLL_TO:
  385.         if (scroll_amount == 1)
  386.         window_set(textsw, TEXTSW_FIRST, 0, NULL);
  387.         else if (scroll_amount == 2)
  388.         window_set(textsw, TEXTSW_FIRST, TEXTSW_INFINITY, NULL);
  389.         textsw_scroll_lines(textsw, -textsw_screen_line_count(textsw));
  390.         break;
  391.     case MUSH_SCROLL_RELATIVE :
  392.         textsw_scroll_lines(textsw, scroll_amount);
  393.     }
  394.     window_set(textsw, TEXTSW_UPDATE_SCROLLBAR, NULL);
  395.     return NOTIFY_DONE;
  396. }
  397.  
  398. /*ARGSUSED*/
  399. Notify_value
  400. destroy_proc(frame, status)
  401. Frame frame;
  402. Destroy_status status;
  403. {
  404.     if (ison(glob_flags, IS_GETTING))
  405.     rm_edfile(-1);
  406.     /* status is ignored -- maybe post notice asking to confirm quit? */
  407.     if (status == DESTROY_CHECKING && ison(glob_flags, DO_UPDATE) &&
  408.     !ask("Your folder has been modified.  Quit anyway?"))
  409.     (void) notify_veto_destroy(frame);
  410.     else
  411.     cleanup(0); /* doesn't return */
  412.     return NOTIFY_DONE;
  413. }
  414.  
  415. /* Initialise the Mush mail icon. */
  416. static void
  417. geticon()
  418. {
  419.     static Rect lrect = { 5, 5, 26, 12 };
  420.  
  421.     mail_icon = icon_create(
  422.     ICON_WIDTH,        64,
  423.     ICON_HEIGHT,        64,
  424.     ICON_FONT,        mush_font,
  425.     ICON_IMAGE,        &mail_icon_image1,
  426.     ICON_LABEL,        "",
  427.     ICON_LABEL_RECT,    &lrect,
  428.     0);
  429. }
  430.  
  431. /* Initialise all the cursors used. */
  432. static void
  433. init_cursors()
  434. {
  435.     extern Pixrect mouse_left, mouse_middle, mouse_right, bent_arrow;
  436.     extern Cursor bentarrow;
  437.  
  438.     l_cursor = cursor_create(
  439.     CURSOR_XHOT,    3,
  440.     CURSOR_YHOT,    3,
  441.     CURSOR_OP,    PIX_SRC,
  442.     CURSOR_IMAGE,    &mouse_left,
  443.     NULL);
  444.     m_cursor = cursor_create(
  445.     CURSOR_XHOT,    3,
  446.     CURSOR_YHOT,    3,
  447.     CURSOR_OP,    PIX_SRC,
  448.     CURSOR_IMAGE,    &mouse_middle,
  449.     NULL);
  450.     r_cursor = cursor_create(
  451.     CURSOR_XHOT,    3,
  452.     CURSOR_YHOT,    3,
  453.     CURSOR_OP,    PIX_SRC,
  454.     CURSOR_IMAGE,    &mouse_right,
  455.     NULL);
  456.     bentarrow = cursor_create(
  457.     CURSOR_XHOT,    8,
  458.     CURSOR_YHOT,    8,
  459.     CURSOR_OP,    PIX_SRC|PIX_DST,
  460.     CURSOR_IMAGE,    &bent_arrow,
  461.     NULL);
  462.     coffee = cursor_create(
  463.     CURSOR_XHOT,    8,
  464.     CURSOR_YHOT,    8,
  465.     CURSOR_OP,    PIX_SRC,
  466.     CURSOR_IMAGE,    &coffee_cup,
  467.     NULL);
  468. }
  469.  
  470. /* show the timeout cursor (coffee cup) when "on" is TRUE.  This routine
  471.  * may be called many times in layers of locking mechanisms, so be careful
  472.  * not to unlock cursors until "on" has been FALSE as many times as it has
  473.  * been TRUE.
  474.  */
  475. void
  476. timeout_cursors(on)
  477. int on;
  478. {
  479.     Window win;
  480.     Frame subframe;
  481.     static int locked, numwins;
  482.     int i = 0, j;
  483.     static struct {
  484.     Cursor cursor;
  485.     Window win;
  486.     } win_curs[64];
  487.  
  488.     on? locked++ : locked--;
  489.     if (istool < 2 || locked > 1 || locked == 1 && on == 0)
  490.     return;
  491.     if (on) {
  492.     for (numwins = 0; win = window_get(tool, FRAME_NTH_SUBWINDOW, numwins);
  493.         numwins++) {
  494.         win_curs[numwins].cursor =
  495.                 cursor_copy((Cursor) window_get(win, WIN_CURSOR));
  496.         win_curs[numwins].win = win;
  497.         window_set(win, WIN_CURSOR, coffee, NULL);
  498.     }
  499.     while (subframe = window_get(tool, FRAME_NTH_SUBFRAME, i++))
  500.         for (j = 0; win = window_get(subframe, FRAME_NTH_SUBWINDOW, j);
  501.             j++,numwins++) {
  502.         win_curs[numwins].cursor =
  503.                 cursor_copy((Cursor) window_get(win, WIN_CURSOR));
  504.         win_curs[numwins].win = win;
  505.         window_set(win, WIN_CURSOR, coffee, NULL);
  506.         }
  507.     } else {
  508.     for (j = 0; j < numwins; j++) {
  509.         window_set(win_curs[j].win, WIN_CURSOR, win_curs[j].cursor, NULL);
  510.         cursor_destroy(win_curs[j].cursor);
  511.     }
  512.     }
  513. }
  514.  
  515. /*
  516.  * If the user has specified an alternate icon or set of icons in
  517.  * his .mushrc file, copy the image(s) over the defaults.
  518.  */
  519. void
  520. check_icons()
  521. {
  522.     Pixrect *icon_mpr;
  523.     char errbuf[256], *icon_file, *icon_path;
  524.     int isdir;
  525.  
  526.     if ((icon_file = do_set(set_options, "mail_icon")) && *icon_file) {
  527.     isdir = 0;
  528.     icon_path = getpath(icon_file, &isdir);
  529.     if (isdir == 0) {
  530.         if (!(icon_mpr = icon_load_mpr(icon_path, errbuf)))
  531.         error("Error loading mail icon file:\n%s",errbuf);
  532.         else
  533.         pr_rop(&mail_icon_image1, 0,0,64,64, PIX_SRC, icon_mpr, 0, 0);
  534.     }
  535.     }
  536.     if ((icon_file = do_set(set_options, "newmail_icon")) && *icon_file) {
  537.     isdir = 0;
  538.     icon_path = getpath(icon_file, &isdir);
  539.     if (isdir == 0) {
  540.         if (!(icon_mpr = icon_load_mpr(icon_path, errbuf)))
  541.         error("Error loading newmail icon file:\n%s",errbuf);
  542.         else
  543.         pr_rop(&mail_icon_image2, 0,0,64,64, PIX_SRC, icon_mpr, 0, 0);
  544.     }
  545.     }
  546. }
  547.